#!/usr/bin/env python


import os
from utils.singleton import singleton
from conf import Conf
import sys
import time
import platform
import utils
from xml.etree.ElementTree import ElementTree
#from conf import ServerConf




SERVER_PATH="server/"
SERVER_CONF="conf/server/"


@singleton
class Servers:
    def __init__(self):
        self.dir=SERVER_PATH
        self._pipe=None
        self._servers=[]
        
        listDir=os.listdir(self.dir)
        
        #s=Server("All","Server")
        #self._servers.append(s)
        
        for name in listDir:
            s=Server(name,self.dir+'/'+name)
            self._servers.append(s)

        self._currentServer=self._servers[0]
        
        #self.cmdStop="httpd.exe"
    
    def start(self):
        self._currentServer.start()
    
    def stop(self):
        
        self._currentServer.stop()
        #if self._pipe:
        #    self._pipe.terminate()

    def getServerList(self):
        return self._servers
    
    def getCurrentServer(self):
        return self._currentServer
    
    def getServerByName(self,name):
        for server in self._servers:
            if server.name==name:
                return server
    
    #def getEnableServer(self):
    #    return self._servers
  
  
  
    
class Server:
    def __init__(self,dirName="",path=""):
        self._pipe=None
        self.dirName=dirName
        self.name=dirName
        self.path=path
        self.node=-1;
        self.paths={}
        self._data={}
        self.started=False
        self.serverInfo=ServerInfos(self)
        self.serverInfo.readInfo()        
        
        paths=Conf().getServerPaths(self.dirName);
        for path in paths:
            self.addPath(paths[path],path)
        self._conf=ServerConf(self)
        #self.addPath('www','www')
        self.setDocumentRoot(Conf().getServerRoot(self.dirName))
        
        
    
    def start(self):
        self.getAppOnPort()
        self.started=True
        self._conf.apply()
        cmds=self.serverInfo.getStartCmd()        
        for cmd in cmds:
            cmd=cmd.split(" ")
            path=cmd[0].split("/")
            cmd=[path[-1]]+cmd[1:]
            path="/".join(path[0:-1])
            self._pipe=utils.execCmd(self.path+"/"+path,cmd)

        print "start:"+self.dirName
    
        
    def stopCMD(self):
        self.started=True
        self._conf.apply()
        cmds=self.serverInfo.getStopCmd()        
        for cmd in cmds:
            cmd=cmd.split(" ")
            path=cmd[0].split("/")
            cmd=[path[-1]]+cmd[1:]
            path="/".join(path[0:-1])
            utils.execCmd2(self.path+"/"+path,cmd)

        
        
    def stop(self):
        #os.getpid(PID)
        #pulist |find /i "1536"
        #netstat -o -n -a | findstr 0.0:80
        #taskkill /PID pid /F
        #tasklist | findstr pid
        
        self.stopCMD()
        
        if self._pipe:
            if platform.system()=="Windows":
                print utils.execCmd2(["taskkill","/PID",str(self._pipe.pid),"/F","/T"])
            else:
                self._pipe.kill()

            self._pipe.wait()
            self._pipe=None
        print "stop:"+self.dirName
    
    
    def getAppOnPort(self,port=80,close=False):
        result=utils.execCmd2(("netstat -o -n -a | findstr 0.0:"+str(port)).split(" "))
        result=result.split("\n")
        while len(result) and result[0].find(":80 ")==-1:
            result=result[1:]
        
        if len(result)==0:
            return None
        s=result[0].rfind(" ")
        pid=int(result[0][s:])
        result=utils.execCmd2(("tasklist | findstr "+str(port)).split(" "))
        name=result[:result.find(" ")]        
        print "port 80 used by:"+ name + " " +str(pid)
        if close and platform.system()=="Windows":
            print utils.execCmd2(["taskkill","/PID",str(pid),"/F","/T"])
        return (name,pid)
        
    
    def forceCloseWindows(self):
        cmd=self.serverInfo.getStartCmd()[0]
        find=self.path+"/"+cmd
        find=find.replace("//","/")
        find=find.replace("/","\\")
        res=utils.execCmd2(["WMIC","PROCESS","get","Caption,Commandline,Processid"])
        s=res.find(find)
        e=res.find("\r",s)-1
        while res[e]==" ":
            e-=1
        e+=1
        s=res[:e-1].rfind(" ")+1
        r=utils.execCmd2(["taskkill","/PID",res[s:e],"/F"])
    
    
    def addPath(self,name,path):
        self.paths[self.convertPath(path)]=name
    
    def removePath(self,path):
        del self.paths[self.convertPath(path)]
        print(self.paths)
    
    def getPaths(self):
        return self.paths
        
    def setDocumentRoot(self,path):
        self.documentRoot=self.convertPath(path)
        
    def getDocumentRoot(self):
        return self.documentRoot
    
    def convertPath(self,path):
        return os.path.abspath(path).replace("\\","/")
    
    def getServerConf(self):
        return self._conf
    
    def setOption(self,name,value):
        self._data[name]=value
    
    def getOption(self,name):
        if not self._data.has_key(name):
            return None
        return self._data[name]
    
    def getPipe(self):
        self._pipe
        
        
class ServerInfos:
    def __init__(self,server):
        self.ETree=ElementTree()
        self._start=[]
        self._stop=[]
        self.name=""
        self.version=""
        self.server=server
        self.dir=SERVER_CONF
        self._conf="dev"
    
    def readInfo(self):
        path=self.dir+self._conf+'/'+self.server.dirName+"/"+"_serverInfos.xml"
        self.xml=self.ETree.parse(path)
        
        self.name=self.xml.findtext("head/name")
        self.version=self.xml.findtext("head/version")
        
        res=self.xml.findall("start/cmd")
        for n in res:
            self._start.append(n.text)
            
        res=self.xml.findall("stop/cmd")
        for n in res:
            self._stop.append(n.text)
        
    def getStartCmd(self):
        return self._start
    
    def getStopCmd(self):
        return self._stop
    
class ServerConf:
    def __init__(self,server):
        self.server=server
        self.dir=SERVER_CONF
        self._conf="dev"
        
     
    def apply(self):
        self.readFolder(self.dir+self._conf+'/'+os.path.basename(self.server.path))
    
    def readFolder(self,folder):
        dirs=os.listdir(folder);
        for element in dirs:
            path=folder+'/'+element 
            if os.path.isdir(path):
                self.readFolder(path)
            else:
                self.readfile(path)
    
    def readfile(self,file):
        data=open(file,"r").read()
        
        data,virtualServer=self.getBlock(data,"VirtualServeur_TMP",True)
        
        
        paths=self.server.getPaths()
        for path in paths:
            result=self.replaceTag(virtualServer,{"VirtualPath":self.server.convertPath(path), "VirtualName":paths[path]})
            data=self.addDataBetween("VirtualServeur",data,result)
        data=self.replaceTag(data)
        
        path=file[file.find(self._conf)+len(self._conf)+1:]
        open(SERVER_PATH+path,"w+").write(data)
        
    def addDataBetween(self,tag,old,add):
        tag="{{"+tag+"}}"
        startPos=old.find(tag)+len(tag)+1
        old=old[:startPos]+add+old[startPos:]
        return old
        
        
    def replaceTag(self,data,tags={}):
        data=data.replace("${server_path}",os.path.abspath('.').replace("\\","/")+'/'+"Server")
        data=data.replace("${root_path}",self.server.getDocumentRoot())
        
        for tag in tags:
            data=data.replace("${"+tag+"}",tags[tag])
        
        return data
        
        
    def getBlock(self,data,tag,delete=False):
        start=data.find("{{"+tag+"}}")
        end=data.find("{{/"+tag+"}}",start)
        block=data[start+len("{{"+tag+"}}"):end]
        data=data[0:start]+data[end+len("{{/"+tag+"}}"):]
        return (data,block)
        
    
    def getConfigsAvailable(self):
        list=os.listdir(self.dir)
        ret=[]
        for dir in list:
            if(os.path.isdir(self.dir+dir)):
                ret.append(dir)
        return ret
    
    def getDefaultConfig(self):
        return self._conf
        
    def setDefaultConfig(self,dir):
        self._conf=dir


